from app import socketio
from flask_socketio import join_room, leave_room, emit
from app.models import ServerMember
from collections import defaultdict

# 使用字典跟踪用户状态和关联
online_users = set()  # 当前在线用户ID集合
user_rooms = defaultdict(set)  # {user_id: 该用户所在服务器房间集合}
room_users = defaultdict(set)  # {server_id: 该服务器在线用户集合}
socket_user_map = {}  # {socket_id: user_id}


def get_user_servers(user_id):
    """获取用户所属的所有服务器ID"""
    memberships = ServerMember.query.filter_by(user_id=user_id).all()
    return [m.server_id for m in memberships]


def broadcast_user_status(user_id, is_online):
    """广播用户状态变更到所有相关房间"""
    if user_id not in user_rooms:
        return

    status_message = {
        "user_id": user_id,
        "status": "online" if is_online else "offline"
    }

    for server_id in user_rooms[user_id]:
        room_name = f"server_{server_id}"
        emit("user_status_change", status_message, room=room_name)

        # 更新服务器内用户列表
        if is_online:
            room_users[server_id].add(user_id)
        else:
            room_users[server_id].discard(user_id)

        # 同时广播整个服务器在线用户列表
        emit("server_online_users", {
            "server_id": server_id,
            "users": list(room_users[server_id])
        }, room=room_name)


def handle_user_connect(socket_id, user_id):
    """处理用户连接"""
    global online_users, socket_user_map

    # 记录关联关系
    socket_user_map[socket_id] = user_id

    # 获取用户所属的所有服务器
    server_ids = get_user_servers(user_id)

    # 加入所有服务器房间
    for server_id in server_ids:
        room_name = f"server_{server_id}"
        join_room(room_name)
        user_rooms[user_id].add(server_id)

    # 第一次连接时广播在线状态
    if user_id not in online_users:
        online_users.add(user_id)
        broadcast_user_status(user_id, True)


def handle_user_disconnect(socket_id):
    """处理用户断开连接"""
    global online_users, socket_user_map

    # 获取用户ID
    if socket_id not in socket_user_map:
        return

    user_id = socket_user_map[socket_id]
    del socket_user_map[socket_id]

    # 检查用户是否还有其他连接
    has_other_connection = any(
        sid != socket_id and uid == user_id
        for sid, uid in socket_user_map.items()
    )

    # 如果没有其他连接，则广播离线状态
    if not has_other_connection and user_id in online_users:
        online_users.remove(user_id)
        broadcast_user_status(user_id, False)